package com.meta.counter.dao.impl;

import java.util.List;

import com.meta.hibernate.HibernateUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.meta.common.ConstDef;
import com.meta.counter.entity.Counter;
import com.meta.counter.dao.CounterDAO;


@Slf4j
@Component
public class CounterDAOImpl implements CounterDAO{

	private static final int retentation_id = 1;
	@Autowired
	private HibernateUtil hibernateUtil;
	
	@Override
	public boolean newType(String type, int year){
		//逐渐为1的行数必须存在，否则增加一个记录
		String hql = "from Counter c where c.id = " + retentation_id;
		Session session = null;
		Transaction transaction = null;
		session = hibernateUtil.getSession();
		transaction = session.beginTransaction();	
		try{
			Query q = session.createQuery(hql);
			q.setLockMode("c", LockMode.UPGRADE_NOWAIT);
			long key = 0;
			Counter counter=null;
			try{
				counter = (Counter) q.uniqueResult();
				if ( counter == null ){
					transaction.rollback();
					init();
					
					transaction = session.beginTransaction();	
					counter = (Counter) q.uniqueResult();
					if ( counter == null ){
						return false;
					}
				}

			}catch ( Exception e ){
				transaction.rollback();
				log.error(e.getMessage(),e);
				return false;			
			}finally{
				
			}
			key = counter.getCount();
			key = key + 1;
			counter.setCount(key);
			//session.update(counter);
			Counter typeCounter = new Counter();
			typeCounter.setCount(0L);
			typeCounter.setId(key);
			typeCounter.setType(type);
			typeCounter.setYear(year);			
			session.save(typeCounter);//插入新类型计数器，没类型都和年度关联
			transaction.commit();
			
		}catch ( Exception e ){
			transaction.rollback();
			log.error(e.getMessage(),e);
			return false;
		}finally{
			hibernateUtil.closeSession(session);
		}		
		return true;	
	}

	@Override
	public boolean init () {
		String hql = "from Counter c where c.id = " + retentation_id;
		Session session = null;
		Transaction transaction = null;
		List<Counter> counters = hibernateUtil.exeQuery(hql);
		if ( counters == null || counters.size() == 0){
			//插入记录
			Counter c = new Counter();
			c.setId(retentation_id);
			c.setType(ConstDef.COUNTER_TYPE_FIRST);//这个类型保留
			c.setYear(0);
			c.setCount(1);

			try{
				session = hibernateUtil.getSession();
				transaction = session.beginTransaction();	
				session.save(c);
				transaction.commit();
				
			}catch ( Exception e ){
				transaction.rollback();
				e.printStackTrace();				
				try{
					counters = hibernateUtil.exeQuery(hql);
					//下面考虑其他用户可能已经插入一条记录的情况
					if ( counters != null && counters.size() > 0 )
						return true;
					else
						return false;
				} catch ( Exception e1 ){
					log.error(e1.getMessage(),e1);
					return false;
				}				
			}finally{
				hibernateUtil.closeSession(session);
			}
		}		
		return true;

	}

	@Override
	public long nextCounters(String type, int year, int step, int size) {
		//逐渐为1的行数必须存在，否则增加一个记录
		String hql = "from Counter c where c.type = '" + type + "'"
					+ " and c.year = " + year ;
		Session session = hibernateUtil.getSession();
		
		long key = 0L;
		Counter counter=null;
		try{
			Transaction transaction = session.beginTransaction();			
			Query q = session.createQuery(hql);	
			q.setLockOptions(LockOptions.UPGRADE);
			counter = (Counter) q.uniqueResult();
			if( counter == null ){
				transaction.rollback();//add为了释放锁
				newType(type, year);
				transaction = session.beginTransaction();
				
					counter = (Counter) q.uniqueResult();
					if ( counter == null ){
						transaction.rollback();
						return -1;
					}			
					key = counter.getCount();
					counter.setCount(key+size*step);
					key+=step;
					transaction.commit();				
			}
			else {		
				key = counter.getCount();
				counter.setCount(key+size*step);
				key+=step;
				transaction.commit();				
			}
			
		}catch ( Exception e ){
				log.error(e.getMessage(),e);
						
		}finally{
			hibernateUtil.closeSession(session);
		}		
		return key;	
	}


	@Override
	public long nextCounter(String type, int year) {
		return nextCounters(type, year,1, 1);
	}

	@Override
	public long nextCounters(String type, int year, int size) {
		return nextCounters(type,year,1,size);
	}


	@Override
	public long nextCounter(String type) {
		return this.nextCounter(type, 0);
	}

}

